package com.novel.framework.shiro.utils;

import com.novel.common.constants.Constants;
import com.novel.common.exception.business.BusinessException;
import com.novel.framework.shiro.TokenService;
import com.novel.framework.shiro.jwt.utils.JWTUtil;
import com.novel.framework.shiro.realm.UserRealm;
import com.novel.system.domain.LoginUser;
import com.novel.system.domain.SysUser;
import com.novel.system.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;

/**
 * shiro 工具类
 *
 * @author novel
 * @date 2019/4/17
 */
@Component
@Slf4j
public class ShiroUtils {
    private static SysUserService sysUserService;
    private static TokenService tokenService;

    private final SysUserService userService;
    private final TokenService service;

    public ShiroUtils(SysUserService userService, TokenService service) {
        this.userService = userService;
        this.service = service;
    }


    @PostConstruct
    public void init() {
        sysUserService = userService;
        tokenService = service;
    }

    /**
     * 获取当前登录用户
     *
     * @return 用户
     */
    public static SysUser getUser() {
        SysUser user = null;
        LoginUser loginUser = tokenService.getLoginUser(getToken());
        if (loginUser != null) {
            user = loginUser.getUser();
        }

        if (user == null) {
            user = sysUserService.findUserByUserName(getUserName());
        }

        // 用户是否存在
        if (user == null) {
            throw new BusinessException("该帐号不存在(The account does not exist.)");
        }
        return user;
    }

    /**
     * 获取当前登录用户Id
     *
     * @return Id
     */
    public static Long getUserId() {
        return getUser().getId();
    }

    /**
     * 获取当前登录用户Token
     *
     * @return Token
     */
    public static String getToken() {
        Optional<Object> principal = Optional.ofNullable(SecurityUtils.getSubject().getPrincipal());
        return principal.orElse("").toString();
    }

    /**
     * 获取当前登录用户UserName
     *
     * @return UserName
     */
    public static String getUserName() {
        // 解密获得Account
        return JWTUtil.getSubject(getToken());
    }

    /**
     * 获取当前用户sessionId
     *
     * @return sessionId
     */
    public static String getSessionId() {
        // 解密获得Account
        return JWTUtil.getId(getToken());
    }


    /**
     * 获取主体
     *
     * @return 主体
     */
    public static Subject getSubject() {
        return SecurityUtils.getSubject();
    }

    /**
     * 退出指定用户
     *
     * @param userName 退出用户名
     */
    public static void logoutUsersByUserName(String userName) {
        tokenService.delLoginUsersByUserName(userName);
    }


    /**
     * 重新设置用户
     *
     * @param user 用户
     */
    public static void setUser(SysUser user) {
        Subject subject = getSubject();
        PrincipalCollection principalCollection = subject.getPrincipals();

        String realmName = principalCollection.getRealmNames().iterator().next();
        log.debug("realmName:" + realmName);
//        String sessionId = UUID.randomUUID().toString();

//        redisTemplate.delete(Constants.ACCOUNT + user.getUserName() + ":*");//删除缓存，重新签名
//        redisTemplate.opsForValue().set(Constants.ACCOUNT + user.getUserName() + ":" + sessionId, user, jwtProperties.getTokenExpireTime(), TimeUnit.MINUTES);

//        String token = JWTUtil.sign(user, sessionId);

        tokenService.setUser(getUserName(), user);

        LoginUser loginUser = tokenService.getLoginUser(getToken());
//        loginUser.setUser(user);
        String token = tokenService.refreshToken(loginUser);

//        PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(token.toString(), realmName);
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletResponse response = attributes.getResponse();
            if (response != null) {
                response.setHeader(Constants.AUTHORIZATION, token);
                response.setHeader("Access-Control-Expose-Headers", Constants.AUTHORIZATION);
            }
        }
//        clearCachedAuthorizationInfo();
        // 重新加载Principal
//        subject.runAs(newPrincipalCollection);
        tokenService.delLoginUsersBySessionId(getSessionId());
    }

    /**
     * 清除权限缓存
     */
    public static void clearCachedAuthorizationInfo() {
        RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
        UserRealm realm = (UserRealm) rsm.getRealms().iterator().next();
        realm.clearCachedAuthorizationInfo();
    }
}
